define(() => {
    return {

        ..._,

        isDefined(value) {
            return !this.isUndefined(value);
        },

        isURL(value) {
            return this.isString(value) && /^((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(:[0-9]+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)/.test(value);
        },

        isHexColor(value) {
            return this.isString(value) && /^\#[0-9a-zA-Z]{3,6}$/.test(value);
        },

        getPrototype(value) {
            const temp = Object.prototype.toString.call(value);
            return temp.match(/^\[object (.*)\]/)[1];
        },

        isDiv(value) {
            return this.getPrototype(value) === "HTMLDivElement";
        },

        isCanvas(value) {
            return this.getPrototype(value) === "HTMLCanvasElement";
        },

        isImage(value) {
            return this.getPrototype(value) === "HTMLImageElement";
        },

        assert(expression, error) {
            if(expression)
                return;
            throw this.isError(error) ? error : new Error(error);
        },

        optionsInject(that, options, initializers = {}, checkers = {}) {
            Object.keys(that).forEach(key => {
                let value = options[key];
                if(this.isFunction(initializers[key]))
                    value = initializers[key](value);
                if(this.isFunction(checkers[key]))
                    this.assert(checkers[key](value), `options property ${key} invalid`);
                if(this.isUndefined(value))
                    return;
                if(this.isSymbol(that[key]) && !this.isSymbol(value))
                    return;
                that[key] = value;
            });
        }
        
    };
});